package com.bsj.power.pls.queue;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsj.consumerQ.function.HandleRunT;
import com.bsj.consumerQ.method.QueueAndRunT;
import com.bsj.power.common.config.cached.*;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.constant.UWBPosConstant;
import com.bsj.power.common.def.dto.RedisSceneInfo;
import com.bsj.power.common.def.dto.cardReport.BindCardDTO;
import com.bsj.power.common.def.entity.job.QualityPlan;
import com.bsj.power.common.def.entity.locationDevice.LocationDevice;
import com.bsj.power.common.def.entity.path.PathPoint;
import com.bsj.power.common.def.entity.personnel.Personnel;
import com.bsj.power.common.def.vo.pls.httpVo.HttpTagPosVO;
import com.bsj.power.common.def.vo.web.job.JobCacheVO;
import com.bsj.power.common.mapper.PersonnelMapper;
import com.bsj.power.common.mapper.QualityPlanMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description JobSignInQueue
 * @time 2024/6/20 15:35
 */
@Slf4j
@Component
public class JobSignInQueue extends QueueAndRunT<HttpTagPosVO> {

    @Autowired
    private RedisCached redisCached;

    @Resource
    private QualityPlanMapper qualityPlanMapper;

    @Resource
    private PersonnelMapper personnelMapper;

    @Autowired
    private BindCardCached bindCardCached;

    @Autowired
    private PersonnelCached personnelCached;

    @Autowired
    private LocationDeviceCached locationDeviceCached;

    public void start() {
        start("jobSignInQueue", new HandleRunT<HttpTagPosVO>() {

            @Override
            public void doRun(List<HttpTagPosVO> list) {
                for (HttpTagPosVO httpTagPosVO : list) {
                    String deviceName = httpTagPosVO.getSn();
                    LocationDevice locationDevice = locationDeviceCached.hgetLocationDeviceInfo(deviceName);
                    if (locationDevice == null) {
                        continue;
                    }
                    //绑卡信息
                    BindCardDTO bindCardDTO = bindCardCached.hgetBindCardInfo(RedisConstant.BIND_CARD_REDIS_DEVICE_NAME_KEY + locationDevice.getDeviceName());
                    if (bindCardDTO == null) {
                        continue;
                    }
                    String empNo = bindCardDTO.getEmpNo();
                    //当前卡所绑定的人（负责人信息）,作业人员不处理，只需要处理负责人；由于qc信息也是从工单同步过来，从某种意义上来说QC也是负责人
                    Personnel personnel = personnelCached.hgetPersonnelInfo(empNo);
//                    //当前卡所绑定的人（作业人员）
//                    WorkPersonnel workPersonnel = workPersonnelCached.getWorkPersonnelInfo(empNo);
                    if (personnel == null) {
                        continue;
                    }
                    //最终目的为判断QC是否和负责人同时在一个区域，所以跳过

                    Integer personnelId = personnel.getPersonnelId();
//                    if (workPersonnel != null) {
//                        continue;
//                    }
                    long time = httpTagPosVO.getTime();
                    Date date = new Date(time);
                    //设备当前位置
                    double[] pos = httpTagPosVO.getPos();
                    List<JobCacheVO> jobCacheVOS = bindCardDTO.getJobCacheVOS();
                    //工单信息不存在
                    if (CollectionUtils.isEmpty(jobCacheVOS)) {
                        continue;
                    }
                    for (JobCacheVO jobCacheVO : jobCacheVOS) {
                        //负责人工号
                        String directorEmpNo = jobCacheVO.getEmpNo();
                        if (StringUtils.isBlank(directorEmpNo)) {
                            continue;
                        }
                        //是否是工单负责人
                        boolean isDirector = empNo.equals(directorEmpNo);
                        //负责人最新位置
                        HttpTagPosVO directorPos = null;
                        if (!isDirector) {
                            //负责人绑卡信息
                            BindCardDTO directorBindCardDTO = bindCardCached.hgetBindCardInfo(RedisConstant.BIND_CARD_REDIS_EMP_NO_KEY + directorEmpNo);
                            if (directorBindCardDTO != null) {
                                //获取负责人的位置
                                String str = redisCached.get(UWBPosConstant.REDIS_TAG_POS_KEY + directorBindCardDTO.getDeviceName());
                                if (StringUtils.isNotBlank(str)) {
                                    directorPos = JSON.parseObject(str, HttpTagPosVO.class);
                                }
                            }
                            //负责人或位置为空跳过
                            if (personnelCached.hgetPersonnelInfo(directorEmpNo) == null || directorPos == null || directorPos.getPos() == null) {
                                continue;
                            }
                        }
                        //如果所有QC签点状态为已签点则结束
                        List<QualityPlan> qualityPlans = jobCacheVO.getQualityPlans();
                        if (!CollectionUtils.isEmpty(qualityPlans)) {
                            //筛选出签点异常（未签点）的QC
                            List<QualityPlan> abnormalQualityPlans = qualityPlans.stream().filter(qualityPlan -> qualityPlan.getQcState().equals(NumericalConstants.ONE)).collect(Collectors.toList());
                            //正常的（已签点）QC
                            List<QualityPlan> newQualityPlans = qualityPlans.stream().filter(qualityPlan -> qualityPlan.getQcState().equals(NumericalConstants.TWO)).collect(Collectors.toList());
                            //代表有QC未签点
                            if (!CollectionUtils.isEmpty(abnormalQualityPlans)) {
                                //作业区域（场景名称）
                                List<PathPoint> pathPoints = getScenePathPoints(jobCacheVO.getWorkArea());
                                if (!CollectionUtils.isEmpty(pathPoints)) {
                                    QualityPlan contractorQualityPlan = null;
                                    QualityPlan maintainQualityPlan = null;
                                    QualityPlan technicalSupportQualityPlan = null;
                                    //暂定每个工单的质量计划中同种类型的QC最多只有一个
                                    for (QualityPlan qualityPlan : abnormalQualityPlans) {
                                        Integer qcType = qualityPlan.getQcType();
                                        if (qcType.equals(NumericalConstants.ONE)) {
                                            contractorQualityPlan = qualityPlan;
                                        } else if (qcType.equals(NumericalConstants.TWO)) {
                                            maintainQualityPlan = qualityPlan;
                                        } else if (qcType.equals(NumericalConstants.THREE)) {
                                            technicalSupportQualityPlan = qualityPlan;
                                        } else {
                                            log.info("QC类型错误{}", qualityPlan);
                                        }
                                    }
                                    Integer contractorQc = jobCacheVO.getContractorQc();
                                    Integer maintainQc = jobCacheVO.getMaintainQc();
                                    Integer technicalSupportQc = jobCacheVO.getTechnicalSupportQc();
                                    //承包商QC
                                    if (contractorQc != null && contractorQc == 1) {
                                        //需要签点
                                        if (contractorQualityPlan != null) {
                                            signInHandle(contractorQualityPlan, jobCacheVO, newQualityPlans, time, pos, isDirector, pathPoints, directorPos);
                                        }
                                    }
                                    //维修QC
                                    if (maintainQc != null && maintainQc == 1) {
                                        if (maintainQualityPlan != null) {
                                            signInHandle(maintainQualityPlan, jobCacheVO, newQualityPlans, time, pos, isDirector, pathPoints, directorPos);
                                        }
                                    }
                                    //技术支持QC
                                    if (technicalSupportQc != null && technicalSupportQc == 1) {
                                        if (technicalSupportQualityPlan != null) {
                                            signInHandle(technicalSupportQualityPlan, jobCacheVO, newQualityPlans, time, pos, isDirector, pathPoints, directorPos);
                                        }
                                    }
                                    //重新写入缓存
                                    jobCacheVO.setQualityPlans(newQualityPlans);
                                    bindCardCached.hsetBindCardInfo(bindCardDTO);
//                                    redisCached.hset(RedisConstant.JOB_ORDER_EVERYDAY_KEY + dateKey, jobCacheVO.getJobNum(), JSON.toJSONString(jobCacheVO));
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    /**
     * 获取场景位置点集
     *
     * @param workArea
     * @return java.util.List<com.bsj.power.common.def.entity.path.PathPoint>
     * @author ljx
     * @time 2024/7/18 19:29
     */
    private List<PathPoint> getScenePathPoints(String workArea) {
        List<PathPoint> pathPoints = new ArrayList<>();
        // TODO 后续改为房间号签点判断
        String sceneStr = redisCached.get(RedisConstant.REDIS_SCENE_INFO + workArea);
        if (StringUtils.isNotBlank(sceneStr)) {
            RedisSceneInfo redisSceneInfo = JSON.parseObject(sceneStr, RedisSceneInfo.class);
            if (redisSceneInfo != null) {
                String scenePoint = redisSceneInfo.getScenePoint();
                if (StringUtils.isNotBlank(scenePoint)) {
                    JSONObject jsonObject = JSONObject.parseObject(scenePoint);
                    JSONArray startArray = jsonObject.getJSONArray("start");
                    JSONArray endArray = jsonObject.getJSONArray("end");
                    //开始点
                    Double z = startArray.getDouble(1);
                    Double starX = startArray.getDouble(0);
                    Double starY = startArray.getDouble(2);
                    pathPoints.add(new PathPoint(starX, starY, z));
                    //结束点
                    Double endX = endArray.getDouble(0);
                    Double endY = endArray.getDouble(2);
                    pathPoints.add(new PathPoint(endX, endY, z));
                    //第二点
                    pathPoints.add(new PathPoint(endX, starY, z));
                    //第三点
                    pathPoints.add(new PathPoint(starX, endY, z));
                }
            }
        }
        return pathPoints;
    }

    /**
     * 签点处理（能进入此方法的都是未签点的）
     *
     * @param qualityPlan
     * @param jobCacheVO
     * @param newQualityPlans
     * @param time
     * @param pos
     * @param isDirector
     * @param pathPoints
     * @param directorPos
     * @return void
     * @author ljx
     * @time 2024/6/20 20:37
     */
    private void signInHandle(QualityPlan qualityPlan, JobCacheVO jobCacheVO, List<QualityPlan> newQualityPlans, long time, double[] pos, boolean isDirector, List<PathPoint> pathPoints, HttpTagPosVO directorPos) {
        String qualityPoint = qualityPlan.getQualityPoint();
        //是否为R，如果为R则无需定位判断
        if (StringUtils.isNotBlank(qualityPoint) && qualityPoint.toUpperCase().equals("R")) {
            //修改QC状态
            qualityPlan.setQcState(NumericalConstants.TWO);
            qualityPlanMapper.updateById(qualityPlan);
        } else {
            Date startTime = jobCacheVO.getStartTime();
            Date targetTime = jobCacheVO.getTargetTime();
            //是否在工单计划开始时间内或目标开始时间内（小于计划开始时间或小于目标开始时间）
            if ((startTime != null && time <= startTime.getTime()) || (targetTime != null && time <= targetTime.getTime())) {
                //当前设备所绑定的如果是工单负责人
                if (isDirector) {
                    //暂定QC人员类型为负责人（仅表示他的类型是负责人类型，并不表示他是本工单的实际负责人，因为qc信息也是从工单同步过来）
                    Personnel eyewitness = personnelMapper.selectOne(Wrappers.<Personnel>lambdaQuery().eq(Personnel::getDirectorId, qualityPlan.getEyewitness()));
                    if (eyewitness != null) {
                        //QC见证人绑卡信息
                        BindCardDTO tempBindCardDTO = bindCardCached.hgetBindCardInfo(RedisConstant.BIND_CARD_REDIS_EMP_NO_KEY + eyewitness.getEmpNo());
                        if (tempBindCardDTO != null) {
                            //获取当前QC位置
                            String str = redisCached.get(UWBPosConstant.REDIS_TAG_POS_KEY + tempBindCardDTO.getDeviceName());
                            if (StringUtils.isNotBlank(str)) {
                                HttpTagPosVO temphttpTagPosVO = JSON.parseObject(str, HttpTagPosVO.class);
                                //同时在这个区域内
                                if (AlarmQueue.isInRange(pathPoints, pos) && AlarmQueue.isInRange(pathPoints, temphttpTagPosVO.getPos())) {
                                    //签点成功
                                    qualityPlan.setQcState(NumericalConstants.TWO);
                                    qualityPlanMapper.updateById(qualityPlan);
                                }
                            }
                        }
                    }
                } else { //当前设备所绑定的如果是QC见证人
                    //同时在这个区域内
                    if (AlarmQueue.isInRange(pathPoints, pos) && AlarmQueue.isInRange(pathPoints, directorPos.getPos())) {
                        //签点成功
                        qualityPlan.setQcState(NumericalConstants.TWO);
                        qualityPlanMapper.updateById(qualityPlan);
                    }
                }
            }
        }
        newQualityPlans.add(qualityPlan);
    }

}
